

#include "stdafx.h"
#include "OpenGL.h"
#include <iostream>
#include "Text.h"
#include <math.h>
#include <vector>
#include <tuple>
#include <gl\gl.h>
#include <gl\GLU.h>
#define FIRST_TIMER 100
using namespace std;
HDC hDC;

HGLRC hGLRC;

HWND hWND;

vector<tuple<float, float, char>>* coord_x_y;

float x = 0; float y = 0;

#define MAX_LOADSTRING 100

// Global Variables:
HINSTANCE hInst;                                // current instance
WCHAR szTitle[MAX_LOADSTRING];                  // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING];            // the main window class name

// Forward declarations of functions included in this code module:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
	_In_opt_ HINSTANCE hPrevInstance,
	_In_ LPWSTR    lpCmdLine,
	_In_ int       nCmdShow)
{
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);

	// TODO: Place code here.

	// Initialize global strings
	LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
	LoadStringW(hInstance, IDC_OPENGL, szWindowClass, MAX_LOADSTRING);
	MyRegisterClass(hInstance);

	// Perform application initialization:
	if (!InitInstance(hInstance, nCmdShow))
	{
		return FALSE;
	}

	HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_OPENGL));

	MSG msg;

	// Main message loop:
	while (GetMessage(&msg, nullptr, 0, 0))
	{
		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	return (int)msg.wParam;
}

//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEXW wcex;

	wcex.cbSize = sizeof(WNDCLASSEX);

	wcex.style = CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc = WndProc;
	wcex.cbClsExtra = 0;
	wcex.cbWndExtra = 0;
	wcex.hInstance = hInstance;
	wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_OPENGL));
	wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
	wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
	wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_OPENGL);
	wcex.lpszClassName = szWindowClass;
	wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
    
	return RegisterClassExW(&wcex);
}

//
//   FUNCTION: InitInstance(HINSTANCE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
	hInst = hInstance; // Store instance handle in our global variable
	coord_x_y = new vector<tuple<float, float, char>>;
	coord_x_y->reserve(10000);
	hWND = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);

	if (!hWND)
	{
		return FALSE;
	}
	
	PIXELFORMATDESCRIPTOR pfd = {
		sizeof(PIXELFORMATDESCRIPTOR),
		1,
		PFD_SUPPORT_OPENGL |
		PFD_DRAW_TO_WINDOW |
		PFD_DOUBLEBUFFER,
		PFD_TYPE_RGBA,
		32,
		0, 0, 0, 0, 0, 0,
		0,
		0,
		0,
		0, 0, 0, 0,
		16,
		0,
		0,
		PFD_MAIN_PLANE,
		0,
		0, 0, 0,
	};

	hDC = GetDC(hWND);
	//SetTimer(hWND, FIRST_TIMER, 17, 0);
	int pixelFormat = ChoosePixelFormat(hDC, &pfd);

	SetPixelFormat(hDC, pixelFormat, &pfd);

	hGLRC = wglCreateContext(hDC);

	wglMakeCurrent(hDC, hGLRC);

	ShowWindow(hWND, nCmdShow);

	UpdateWindow(hWND);

	return TRUE;
}
struct  OpenGLCursor
{
	float CoordX, CoordY;
};
void resize(int width, int height)
{
    glViewport(0, 0, width, height);
   
    glLoadIdentity();
}
OpenGLCursor ConvertMouseCoord(POINT CurrentMouse)
{
	RECT WindowsSize;

	GetClientRect(hWND, &WindowsSize);

	OpenGLCursor MouseOpenGL;

	float x = CurrentMouse.x, h = WindowsSize.right;
	::x = 2 / h;
	float ax = 2 * x / h - 1;

	float y = CurrentMouse.y, w = WindowsSize.bottom;
	::y = 2 / w;
	float ay = 2 * (w - y) / w - 1;

	MouseOpenGL.CoordX = ax;

	MouseOpenGL.CoordY = ay;

	return MouseOpenGL;
}
//
//  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_COMMAND  - process the application menu
//  WM_PAINT    - Paint the main window
//  WM_DESTROY  - post a quit message and return
//
//
int otherfigure = 0;
OpenGLCursor coord;
static float i = 0;
LRESULT CALLBACK WndProc(HWND hWND, UINT message, WPARAM wParam, LPARAM lParam)
{
	PAINTSTRUCT ps;
	HDC hdc;
	switch (message)
	{
	case WM_CREATE:
		
		break;
    case WM_SIZE:
        {
            resize(LOWORD(lParam), HIWORD(lParam));
            
           
        break;
        }
        
	case WM_TIMER:
	if (wParam==FIRST_TIMER){
		i += 0.000001;
		POINT pt;

		GetCursorPos(&pt);

		ScreenToClient(hWND, &pt);

		coord = ConvertMouseCoord(pt);

		InvalidateRect(hWND, NULL, TRUE); 
		break;
	}

	case WM_RBUTTONDOWN:
	{
		POINT pt;

		GetCursorPos(&pt);

		ScreenToClient(hWND, &pt);

		coord = ConvertMouseCoord(pt);

		otherfigure = 2;

		InvalidateRect(hWND, NULL, TRUE);

		break;
	}

	case WM_LBUTTONDOWN:
	{
		POINT ptt;

		GetCursorPos(&ptt);

		ScreenToClient(hWND, &ptt);

		coord = ConvertMouseCoord(ptt);

		otherfigure = 1;

		InvalidateRect(hWND, NULL, TRUE);
		break;
	}

	case WM_COMMAND:
	{
		int wmId = LOWORD(wParam);
		// Parse the menu selections:

		switch (wmId)
		{
		case IDM_ABOUT:
			DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWND, About);
			break;
		case IDM_EXIT:
			DestroyWindow(hWND);
			break;
		default:
			return DefWindowProc(hWND, message, wParam, lParam);
		}
	}
	break;
	case WM_PAINT:
	{
		hdc=BeginPaint(hWND, &ps);
		/*float ran = 1 - (rand() % 100) * 0.01;*/
		glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
		//glClearColor(/*ran, ran / 2, ran / 30*/0, 0, 0, 0);
        
		if (!coord_x_y->empty())
		{
			for (int i = 0;i < coord_x_y->size();i++)
			{
				if (std::get<2>(coord_x_y->at(i)) == 'c')
				{
					glBegin(GL_POLYGON);
					glColor3f(0, 0, 1);
					for (float k = 0.0; k <= 2 * 3.14; k += 3.14 / 16) {
						glVertex2f(std::get<0>(coord_x_y->at(i)) + ::x * 20 * sin(k), std::get<1>(coord_x_y->at(i)) + ::y * 20 * cos(k));
					}
					glEnd();
				}
				else
				{
					glBegin(GL_TRIANGLES);
					glColor3f(1, 0, 0);

					glVertex2f(std::get<0>(coord_x_y->at(i)), std::get<1>(coord_x_y->at(i)) + y * 30);
					glVertex2f(std::get<0>(coord_x_y->at(i)) - x * 30, std::get<1>(coord_x_y->at(i)) - y * 30);
					glVertex2f(std::get<0>(coord_x_y->at(i)) + x * 30, std::get<1>(coord_x_y->at(i)) - y * 30);
					glEnd();
				}
			}
		}

		if (otherfigure == 2)
		{
			glBegin(GL_POLYGON);
			glColor3f(0, 0, 1);
			for (float i = 0.0; i <= 2 * 3.14; i += 3.14 / 30) {
				glVertex2f(coord.CoordX + ::x * 20 * sin(i), coord.CoordY + ::y * 20 * cos(i));
			}
			coord_x_y->push_back(make_tuple(coord.CoordX, coord.CoordY, 'c'));
			glEnd();
		}
		if (otherfigure == 1)
		{
			glBegin(GL_TRIANGLES);
			glColor3f(1, 0, 0);

			glVertex2f(coord.CoordX, coord.CoordY + y * 30);
			glVertex2f(coord.CoordX - x * 30, coord.CoordY - y * 30);
			glVertex2f(coord.CoordX + x * 30, coord.CoordY - y * 30);
			coord_x_y->push_back(make_tuple(coord.CoordX, coord.CoordY, 't'));
			glEnd();

		}
		/*glColor3f(1 - (rand() % 255) * 0.0040, 1 - (rand() % 255) * 0.0040, 1 - (rand() % 255) * 0.0040);
		glBegin(GL_TRIANGLES);
		glVertex2f(coord.CoordX, coord.CoordY + y * 30);
		glVertex2f(coord.CoordX - x * 30, coord.CoordY - y * 30);
		glVertex2f(coord.CoordX + x * 30, coord.CoordY - y * 30);
		glEnd();*/
		SwapBuffers(hDC);
		EndPaint(hWND, &ps);
	}
	break;
	case WM_ERASEBKGND:
		return 1;
	case WM_DESTROY:
		KillTimer(hWND, 1);
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWND, message, wParam, lParam);
	}
	return 0;
}

// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	UNREFERENCED_PARAMETER(lParam);
	switch (message)
	{
	case WM_INITDIALOG:
		return (INT_PTR)TRUE;

	case WM_COMMAND:
		if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
		{
			EndDialog(hDlg, LOWORD(wParam));
			return (INT_PTR)TRUE;
		}
		break;
	}
	return (INT_PTR)FALSE;
}